#pragma once
#include "MaterialManager.h"

namespace Graphics{
	// Define the constant data used to communicate with shaders.
	struct sharedData{
		Utility::Math::Matrix<4,4> viewProjMatrix;
		Utility::Math::Matrix<4,4> viewMatrix;
		Utility::Math::Matrix<4,4> projectionMatrix;
	    Utility::Math::Vector<float,3> camPosition;
		Utility::Math::Vector<float,3> light;
		float sinTime;
		float padding;
	};

	struct instanceData{
		Utility::Math::Matrix<4,4> worldMatrix;
		Utility::Math::Matrix<4,4> worldInverseTransposeMatrix;
	};

	struct materialData{
		Utility::Math::Vector<float,4> colorDiffuse;
		Utility::Math::Vector<float,4> colorAmbient;
		Utility::Math::Vector<float,4> colorEmissive;
		Utility::Math::Vector<float,4> colorSpecular;
		Utility::Math::Vector<float,4> colorTransparent;
		float colorTransparency;
		float colorShininess;
		float padding1,padding2;
	};

	class DX11MaterialManager : public MaterialManager{
	public:
		DX11MaterialManager();
		~DX11MaterialManager();

		void initialize(RenderContext* renderContext);

		unsigned int addConstantBuffer(ID3D11Buffer* buffer);

		void setMaterial(unsigned int id);
		void setPixelShader(unsigned int id);
		void setVertexShader(unsigned int id);
		void setComputeShader(unsigned int id);

		void setDepthStencil(bool enable);
		void setInstanceShaderVariables(MeshPtr mesh);
		void setJointFrame(std::vector<Utility::Math::Matrix<4,4>> &joints, int controllerId);
		void setSharedShaderVariables(ICameraPtr camera);

	private:
		void updateSharedBuffer(ICameraPtr camera);
		void updateInstanceBuffer(MeshPtr mesh);
		void updateMaterialBuffer(unsigned int id);
		void createConstantBuffers(RenderContext* renderContext);

		std::map<unsigned int, ID3D11Buffer*> m_constantBuffers;
		ID3D11BlendState	*m_blendStateBlend, 
							*m_blendStateNoBlend;

		ID3D11DepthStencilState *m_writeEnabled,
								*m_writeDisabled;

		unsigned int 	m_constantBufferId;
	};
}